%%%----------------------------------------------------------------------
%%% File    : cus_ejabberd_c2s.erl
%%% Author  : chen.kangmin
%%%----------------------------------------------------------------------

-module(cus_do).
-author('chen.kangmin').


-include("logger.hrl").
-include("ejabberd.hrl").
-include("cus_pb.hrl").
-include("cus.hrl").


-export([
    do_login/1,
    do_message/3,
    do_message_ack/3,
    do_stop/0
        ]).


-export([push_user/1, pack_proto_conversation_info/1]).


do_login(Record) ->
    Uid = Record#login.uid,
    put(uid, Uid),
    Pid = self(),
    case cus_util:is_backend_user(Uid) of
        true ->   %%Android后台进程不需要登录
            UserInfo = #userinfo{uid = Uid,
                                 mutenotofication = 0,
                                 pushcontent = 0,
                                 blacks = "",
                                 follows = "",
                                 emotions = "",
                                 latelyemotions = "",
                                 mutenotofications = "",
                                 sticks = ""},
            RespRecord = #loginresp{userinfo = UserInfo},
            open_session(Uid, Pid),
            put(login, true),
            ?INFO_MSG("ANDROID PUSH : ~p LOGIN SUCCESS", [Uid]),
            Pid ! {router, RespRecord};
        _ ->
            Token = Record#login.token,
            case cus_token_redis:get_user_token(Uid) of
                Token ->
                    Platform = Record#login.platform,
                    PushKey = Record#login.pushkey,
                    case cus_user:login(Uid, Platform, PushKey) of
                        [CusUser, ConversationMessageList] ->
                            PushUser = push_user(CusUser),
                            mnesia:dirty_write(cus_push_user_tab, PushUser),
                            UserInfo = #userinfo{uid = Uid,
                                                 mutenotofication = CusUser#cus_user.muteNotofication,
                                                 pushcontent = CusUser#cus_user.pushContent,
                                                 blacks = string:join([string:join(tuple_to_list(X), "@") || X <- CusUser#cus_user.blacks], ","),
                                                 follows = get_conversation_infos(CusUser#cus_user.follows, []),
                                                 emotions = string:join([string:join(tuple_to_list(X), "@") || X <- CusUser#cus_user.emotions], ","),
                                                 latelyemotions = string:join([string:join(tuple_to_list(X), "@") || X <- CusUser#cus_user.latelyEmotions], ","),
                                                 mutenotofications = get_conversation_infos(CusUser#cus_user.muteNotofications, []),
                                                 sticks = get_conversation_infos(CusUser#cus_user.sticks, [])},
                            ConversationMessages = [begin
                                                        #conversationmessage{totalnumber = Total,
                                                                             msg = Messages}
                                                    end || {Total, Messages} <- ConversationMessageList],
                            RespRecord = #loginresp{userinfo = UserInfo,
                                                    conversationmessage = ConversationMessages},
                            open_session(Uid, Pid),
                            put(login, true),
                            ?INFO_MSG("USER : ~p LOGIN SUCCESS", [Uid]),
                            Pid ! {router, RespRecord};
                        _ ->
                            cus_util:err("0003", "LOGIN ERROR")
                    end;
                _ ->
                    cus_util:err("0002", "TOKEN ERROR")
            end
    end.


%% 消息逻辑
do_message(undefined, _Uid, Message) ->
    ?ERROR_MSG("do message : ~p error, user not login", [Message]);
do_message(true, Uid, Message) ->
    ?INFO_MSG("User : ~p send message : ~p", [Uid, Message]),
    Cid = Message#msg.conversationid,
    ClientMid = Message#msg.mid,
    Time = Message#msg.msgtime,
    CType = cus_util:conversation_type(Cid),
    MType = Message#msg.msgtype,
    case check_ctype_mtype(CType, MType) of
        true ->
            case cus_util:conversation_type(Cid) of
                ?DANLIAO ->   %% 单聊需要校验黑名单
                    QuanID = cus_util:get_quan_id_from_cid(Cid),
                    Info = cus_conversation:conversation_info(Cid),
                    ReceiveUid = lists:delete(Uid, Info#cus_conversation.members),
                    ReceiveUserInfo = cus_user:user_info(ReceiveUid),
                    case ?member({QuanID, Uid}, ReceiveUserInfo#cus_user.blacks) of
                        true ->
                            Extra = [{"msgSendStatus", "black_failed"}],
                            ack(Uid, "", ClientMid, Time, Info, Extra);
                        _ ->
                            real_do_message(Uid, Cid, Message)
                    end;
                _ ->
                    real_do_message(Uid, Cid, Message)
            end;
        _ ->
            ?ERROR_MSG("do message error, Message : ~p", [Message])
    end.


do_message_ack(undefined, _Uid, MsgAck) ->
    ?ERROR_MSG("do message ack: ~p error, user not login", [MsgAck]);
do_message_ack(true, Uid, MsgAck) ->
    Mid = MsgAck#messageack.mid,
    List = re:split(Mid, "_", [{return, list}]),
    Seq = lists:last(List),
    Cid = string:join(lists:delete(Seq, List), "_"),
    cus_user:update_conversation_read_seq(Uid, Cid, ?l2i(Seq)).


do_stop() ->
    Uid = get(uid),
    SessionID = get(session_id),
    case Uid of
        undefined ->
            skip;
        _ ->
            ejabberd_sm:close_session(SessionID, ?l2b(Uid), ?SERVER, ?RESOURCE)
    end,
    ?INFO_MSG("USER: ~p CLOSED", [Uid]).


check_ctype_mtype(?QUANLIAO, ?CORNUCOPIA) ->
    true;
check_ctype_mtype(_CType, ?CORNUCOPIA) ->
    false;
check_ctype_mtype(?DANLIAO, ?GIFT) ->
    true;
check_ctype_mtype(_CType, ?GIFT) ->
    false;
check_ctype_mtype(_CType, _MType) ->
    true.


real_do_message(Uid, Cid, Message) ->
    ClientMid = Message#msg.mid,
    Message1 = server_handle_message(Message),
    case cus_conversation:store_message(Cid, Uid, Message1) of
        [repeat, ServerMessage, Info] ->
            Extra = get_extra_from_message(ServerMessage),
            ServerMid = ServerMessage#msg.mid,
            Time = ServerMessage#msg.msgtime,
            ack(Uid, ServerMid, ClientMid, Time, Info, Extra);
        [new, ServerMessage, Info] ->
            ServerMid = ServerMessage#msg.mid,
            MType = ServerMessage#msg.msgtype,
            case app_request(ServerMessage, Uid, Info, MType) of
                {true, FinalMessage} ->
                    RouterUsers = get_router_users(Uid, Info, FinalMessage),
                    Extra = get_extra_from_message(FinalMessage),
                    Time = FinalMessage#msg.msgtime,
                    spawn(fun() -> ack(Uid, ServerMid, ClientMid, Time, Info, Extra) end),
                    Alert = get_push_alert(FinalMessage),
                    spawn(fun() -> route_message(Uid, RouterUsers, FinalMessage, Cid, Alert) end);
                _ ->
                    Seq = Info#cus_conversation.seq,
                    cus_conversation:cancel_message(Cid, ClientMid, ServerMid, Seq)
            end;
        Other ->
            ?ERROR_MSG("store message error, Message : ~p, reason : ~p", [Message1, Other])
    end.


app_request(Message, Uid, Info, ?CORNUCOPIA) ->
    Url = cus_config:app_api() ++ "/lottery/v2/genGoldCoinLottery",
    Token = cus_token_redis:get_user_token(Uid),
    UserIds = [?l2b(Item) || Item <- Info#cus_conversation.members],
    Cid = Info#cus_conversation.cid,
    QuanId = cus_util:get_quan_id_from_cid(Cid),
    Source = case cus_util:conversation_type(Cid) of
                 ?QUANLIAO ->
                     1;
                 ?TAOLUNZU ->
                     2;
                 _ ->
                     4
             end,
    Content = Message#msg.content,
    {ok, {obj, JsonList} = ContentJson, _} = rfc4627:decode(Content),
    {ok, Amount} = rfc4627:get_field(ContentJson, "amount"),
    {ok, Second} = rfc4627:get_field(ContentJson, "second"),
    {ok, Dev} = rfc4627:get_field(ContentJson, "dev"),
    {ok, Ver} = rfc4627:get_field(ContentJson, "ver"),
    ParamsList = [{"token", ?l2b(Token)},
                  {"spaceId", ?l2b(QuanId)},
                  {"convId", ?l2b(Cid)},
                  {"userIds", UserIds},
                  {"source", Source},
                  {"amount", Amount},
                  {"second", Second},
                  {"dev", Dev},
                  {"ver", Ver}],
    Params = rfc4627:encode({obj, ParamsList}),
    case cus_util:http_request(Url, "p=" ++ Params) of
        {error, Reason} ->
            ?ERROR_MSG("app request error , reason : ~p~n, url : ~p~n, params : ~p", [Reason, Url, Params]),
            false;
        Data ->
            {ok, Json, _} = rfc4627:decode(Data),
            case rfc4627:get_field(Json, "code") of
                {ok, 200} ->
                    {ok, JsonData} = rfc4627:get_field(Json, "data"),
                    {ok, LotteryId} = rfc4627:get_field(JsonData, "lotteryId"),
                    {ok, St} = rfc4627:get_field(JsonData, "st"),
                    {ok, Et} = rfc4627:get_field(JsonData, "et"),
                    lists:filter(fun({"lotteryId", _}) ->
                                         false;
                                     ({"quanId", _}) ->
                                         false;
                                     ({"st", _}) ->
                                         false;
                                     ({"et", _}) ->
                                         false;
                                     (_Other) ->
                                         true
                                 end, JsonList),
                    JsonList1 = [{"lotteryId", LotteryId}, {"quanId", ?l2b(QuanId)},
                                 {"st", St}, {"et", Et}| JsonList],
                    Content1 = rfc4627:encode({obj, JsonList1}),
                    Message1 = Message#msg{content = Content1},
                    Cid = Message1#msg.conversationid,
                    cus_conversation:update_message(Cid, Message1),
                    {true, Message1};
                {ok, Code} ->
                    ?ERROR_MSG("app request error , code : ~p~n, url : ~p~n, params : ~p", [Code, Url, Params]),
                    false
            end
    end;
app_request(Message, Uid, Info, ?LUCK) ->
    Url = cus_config:app_api() ++ "/box/v2/genWordsBox",
    Token = cus_token_redis:get_user_token(Uid),
    UserIds = [?l2b(Item) || Item <- Info#cus_conversation.members],
    QuanId = cus_util:get_quan_id_from_cid(Info#cus_conversation.cid),
    Source = case cus_util:conversation_type(Info#cus_conversation.cid) of
                 ?QUANLIAO ->
                     1;
                 ?TAOLUNZU ->
                     2;
                 _ ->
                     4
             end,
    Content = Message#msg.content,
    {ok, {obj, JsonList} = ContentJson, _} = rfc4627:decode(Content),
    {ok, Paper} = rfc4627:get_field(ContentJson, "paper"),
    {ok, Dev} = rfc4627:get_field(ContentJson, "dev"),
    {ok, Ver} = rfc4627:get_field(ContentJson, "ver"),
    {ok, Title} = rfc4627:get_field(ContentJson, "title"),
    ParamsList = [{"token", ?l2b(Token)},
                  {"spaceId", ?l2b(QuanId)},
                  {"userIds", UserIds},
                  {"describe", Title},
                  {"source", Source},
                  {"paper", Paper},
                  {"dev", Dev},
                  {"ver", Ver}],
    Params = rfc4627:encode({obj, ParamsList}),
    case cus_util:http_request(Url, "p=" ++ Params) of
        {error, Reason} ->
            ?ERROR_MSG("app request error , reason : ~p~n, url : ~p~n, params : ~p", [Reason, Url, Params]),
            false;
        Data ->
            {ok, Json, _} = rfc4627:decode(Data),
            case rfc4627:get_field(Json, "code") of
                {ok, 200} ->
                    {ok, JsonData} = rfc4627:get_field(Json, "data"),
                    {ok, BoxId} = rfc4627:get_field(JsonData, "boxId"),
                    lists:filter(fun({"boxId", _}) ->
                                         false;
                                     ({"quanId", _}) ->
                                         false;
                                     (_Other) ->
                                         true
                                 end, JsonList),
                    JsonList1 = [{"boxId", BoxId}, {"quanId", ?l2b(QuanId)} | JsonList],
                    Content1 = rfc4627:encode({obj, JsonList1}),
                    Message1 = Message#msg{content = Content1},
                    Cid = Message1#msg.conversationid,
                    cus_conversation:update_message(Cid, Message1),
                    {true, Message1};
                {ok, Code} ->
                    ?ERROR_MSG("app request error , code : ~p~n, url : ~p~n, params : ~p", [Code, Url, Params]),
                    false
            end
    end;
app_request(Message, Uid, Info, ?CHEST) ->
    Url = cus_config:app_api() ++ "/box/v2/genGoldBox",
    Token = cus_token_redis:get_user_token(Uid),
    UserIds = [?l2b(Item) || Item <- Info#cus_conversation.members],
    QuanId = cus_util:get_quan_id_from_cid(Info#cus_conversation.cid),
    Source = case cus_util:conversation_type(Info#cus_conversation.cid) of
                 ?QUANLIAO ->
                     1;
                 ?TAOLUNZU ->
                     2;
                 _ ->
                     4
             end,
    Content = Message#msg.content,
    {ok, {obj, JsonList} = ContentJson, _} = rfc4627:decode(Content),
    {ok, Type} = rfc4627:get_field(ContentJson, "type"),
    {ok, Title} = rfc4627:get_field(ContentJson, "title"),
    {ok, Count} = rfc4627:get_field(ContentJson, "count"),
    {ok, Gold} = rfc4627:get_field(ContentJson, "gold"),
    {ok, Dev} = rfc4627:get_field(ContentJson, "dev"),
    {ok, Ver} = rfc4627:get_field(ContentJson, "ver"),
    ParamsList = [{"token", ?l2b(Token)},
                  {"spaceId", ?l2b(QuanId)},
                  {"userIds", UserIds},
                  {"describe", Title},
                  {"type", Type},
                  {"source", Source},
                  {"count", Count},
                  {"gold", Gold},
                  {"dev", Dev},
                  {"ver", Ver}],
    Params = rfc4627:encode({obj, ParamsList}),
    case cus_util:http_request(Url, "p=" ++ Params) of
        {error, Reason} ->
            ?ERROR_MSG("app request error , reason : ~p~n, url : ~p~n, params : ~p", [Reason, Url, Params]),
            false;
        Data ->
            {ok, Json, _} = rfc4627:decode(Data),
            case rfc4627:get_field(Json, "code") of
                {ok, 200} ->
                    {ok, JsonData} = rfc4627:get_field(Json, "data"),
                    {ok, BoxId} = rfc4627:get_field(JsonData, "boxId"),
                    lists:filter(fun({"boxId", _}) ->
                                         false;
                                     ({"quanId", _}) ->
                                         false;
                                     (_Other) ->
                                         true
                                 end, JsonList),
                    JsonList1 = [{"boxId", BoxId}, {"quanId", ?l2b(QuanId)} | JsonList],
                    Content1 = rfc4627:encode({obj, JsonList1}),
                    Message1 = Message#msg{content = Content1},
                    Cid = Message1#msg.conversationid,
                    cus_conversation:update_message(Cid, Message1),
                    {true, Message1};
                {ok, Code} ->
                    ?ERROR_MSG("app request error , code : ~p~n, url : ~p~n, params : ~p", [Code, Url, Params]),
                    false
            end
    end;
app_request(Message, Uid, Info, ?GIFT) ->
    Url = cus_config:app_api() ++ "/gift/v2/sendGift",
    Token = cus_token_redis:get_user_token(Uid),
    [TargetId] = lists:delete(Uid, Info#cus_conversation.members),
    QuanId = cus_util:get_quan_id_from_cid(Info#cus_conversation.cid),
    Content = Message#msg.content,
    {ok, {obj, JsonList} = ContentJson, _} = rfc4627:decode(Content),
    {ok, GiftId} = rfc4627:get_field(ContentJson, "giftId"),
    {ok, Count} = rfc4627:get_field(ContentJson, "count"),
    {ok, Dev} = rfc4627:get_field(ContentJson, "dev"),
    {ok, Ver} = rfc4627:get_field(ContentJson, "ver"),
    ParamsList = [{"token", ?l2b(Token)},
                  {"targetId", ?l2b(TargetId)},
                  {"spaceId", ?l2b(QuanId)},
                  {"giftId", GiftId},
                  {"count", Count},
                  {"dev", Dev},
                  {"ver", Ver}],
    Params = rfc4627:encode({obj, ParamsList}),
    case cus_util:http_request(Url, "p=" ++ Params) of
        {error, Reason} ->
            ?ERROR_MSG("app request error , reason : ~p~n, url : ~p~n, params : ~p", [Reason, Url, Params]),
            false;
        Data ->
            {ok, Json, _} = rfc4627:decode(Data),
            case rfc4627:get_field(Json, "code") of
                {ok, 200} ->
                    {ok, JsonData} = rfc4627:get_field(Json, "data"),
                    {ok, GiftPurchaseId} = rfc4627:get_field(JsonData, "giftPurchaseId"),
                    lists:filter(fun({"giftPurchaseId", _}) ->
                                         false;
                                     (_Other) ->
                                         true
                                 end, JsonList),
                    JsonList1 = [{"giftPurchaseId", GiftPurchaseId} | JsonList],
                    Content1 = rfc4627:encode({obj, JsonList1}),
                    Message1 = Message#msg{content = Content1},
                    Cid = Message1#msg.conversationid,
                    cus_conversation:update_message(Cid, Message1),
                    {true, Message1};
                {ok, Code} ->
                    ?ERROR_MSG("app request error , code : ~p~n, url : ~p~n, params : ~p", [Code, Url, Params]),
                    false
            end
    end;
app_request(Message, _Uid, _Info, _MType) ->
    {true, Message}.


get_extra_from_message(Message) ->
    case Message#msg.msgtype of
        ?DICE_GAME ->
            Content = Message#msg.content,
            {ok, Json, _} = rfc4627:decode(Content),
            {ok, Num} = rfc4627:get_field(Json, "resultNum"),
            [{"resultNum", Num}];
        ?STONE_GAME ->
            Content = Message#msg.content,
            {ok, Json, _} = rfc4627:decode(Content),
            {ok, Num} = rfc4627:get_field(Json, "resultNum"),
            [{"resultNum", Num}];
        ?BLACK_GAME ->
            Content = Message#msg.content,
            {ok, Json, _} = rfc4627:decode(Content),
            {ok, Num} = rfc4627:get_field(Json, "resultNum"),
            [{"resultNum", Num}];
        ?GIFT ->
            Content = Message#msg.content,
            {ok, Json, _} = rfc4627:decode(Content),
            {ok, GiftPurchaseId} = rfc4627:get_field(Json, "giftPurchaseId"),
            [{"giftPurchaseId", GiftPurchaseId}];
        ?CHEST ->
            Content = Message#msg.content,
            {ok, Json, _} = rfc4627:decode(Content),
            {ok, BoxId} = rfc4627:get_field(Json, "boxId"),
            {ok, QuanId} = rfc4627:get_field(Json, "quanId"),
            [{"boxId", BoxId}, {"quanId", QuanId}];
        ?LUCK ->
            Content = Message#msg.content,
            {ok, Json, _} = rfc4627:decode(Content),
            {ok, BoxId} = rfc4627:get_field(Json, "boxId"),
            {ok, QuanId} = rfc4627:get_field(Json, "quanId"),
            [{"boxId", BoxId}, {"quanId", QuanId}];
        ?CORNUCOPIA ->
            Content = Message#msg.content,
            {ok, Json, _} = rfc4627:decode(Content),
            {ok, LotteryId} = rfc4627:get_field(Json, "lotteryId"),
            {ok, QuanId} = rfc4627:get_field(Json, "quanId"),
            {ok, St} = rfc4627:get_field(Json, "st"),
            {ok, Et} = rfc4627:get_field(Json, "et"),
            [{"lotteryId", LotteryId}, {"quanId", QuanId}, {"st", St}, {"et", Et}];
        _ ->
            []
    end.


server_handle_message(Message) ->
    case Message#msg.msgtype of
        ?DICE_GAME ->
            Content = Message#msg.content,
            {ok, {obj, JsonList}, _} = rfc4627:decode(Content),
            lists:filter(fun({"resultNum", _}) ->
                                 false;
                             (_Other) ->
                                 true
                         end, JsonList),
            Num = cus_util:random(6),
            JsonList1 = [{"resultNum", Num} | JsonList],
            Content1 = rfc4627:encode({obj, JsonList1}),
            Message#msg{content = Content1};
        ?STONE_GAME ->
            Content = Message#msg.content,
            {ok, {obj, JsonList}, _} = rfc4627:decode(Content),
            lists:filter(fun({"resultNum", _}) ->
                                 false;
                             (_Other) ->
                                 true
                         end, JsonList),
            Num = cus_util:random(3),
            JsonList1 = [{"resultNum", Num} | JsonList],
            Content1 = rfc4627:encode({obj, JsonList1}),
            Message#msg{content = Content1};
        ?BLACK_GAME ->
            Content = Message#msg.content,
            {ok, {obj, JsonList}, _} = rfc4627:decode(Content),
            lists:filter(fun({"resultNum", _}) ->
                                 false;
                             (_Other) ->
                                 true
                         end, JsonList),
            Num = cus_util:random(2),
            JsonList1 = [{"resultNum", Num} | JsonList],
            Content1 = rfc4627:encode({obj, JsonList1}),
            Message#msg{content = Content1};
        _ ->
            Message
    end.


open_session(Uid, Pid) ->
    [begin
         {_Sid, OldPid} = element(2, Session),
         Kick = #kick{time = cus_util:utc_str()},
         OldPid ! {router, Kick},
         gen_server:cast(OldPid, closed)
     end || Session <- ejabberd_sm:get_user_sessions(?l2b(Uid), ?SERVER)],
    SessionID = {os:timestamp(), Pid},
    ejabberd_sm:open_session(SessionID, ?l2b(Uid), ?SERVER, ?RESOURCE, []),
    put(session_id, SessionID).


route_message(_FromId, [], _Message, _Cid, _Alert) ->
    skip;
route_message(FromId, [ToId | T], Message, Cid, Alert) ->
    To = cus_util:make_jid(?l2b(ToId)),
    From = cus_util:make_jid(?l2b(FromId)),
    Packet = {Message, Cid, Alert},
    ejabberd_router:route(From, To, Packet),
    route_message(FromId, T, Message, Cid, Alert).


get_push_alert(Message) ->
    Content = Message#msg.content,
    {ok, Json, _} = rfc4627:decode(Content),
    MsgType = Message#msg.msgtype,
    case get_show_content(MsgType, Json) of
        skip ->
            skip;
        Text ->
            {ok, UserName} = rfc4627:get_field(Json, "fromUserName"),
            ?unicode(?b2l(UserName) ++ ":" ++ Text)
    end.


get_show_content(?TEXT, Json) ->
    {ok, Text} = rfc4627:get_field(Json, "text"),
    ?b2l(Text);
get_show_content(?AT, Json) ->
    {ok, Text} = rfc4627:get_field(Json, "text"),
    ?b2l(Text);
get_show_content(?IMG, Json) ->
    {ok, IsEmotion} = rfc4627:get_field(Json, "isEmotion"),
    case IsEmotion of
        0 ->
            "[图片]";
        _ ->
            "[表情]"
    end;
get_show_content(?LINK, _Json) ->
    "[链接]";
get_show_content(?VIDEO, _Json) ->
    "[视频]";
get_show_content(?VOICE, _Json) ->
    "[语音]";
get_show_content(?DICE_GAME, _Json) ->
    "[骰子]";
get_show_content(?STONE_GAME, _Json) ->
    "[石头剪刀布]";
get_show_content(?BLACK_GAME, _Json) ->
    "[黑白配]";
get_show_content(?CHEST, _Json) ->
    "[宝箱]";
get_show_content(?CORNUCOPIA, _Json) ->
    "[聚宝盆]";
get_show_content(?LUCK, _Json) ->
    "[拼手气]";
get_show_content(?GIFT, _Json) ->
    "[礼物]";
get_show_content(_Type, _Json) ->
    skip.


ack([$s, $y, $s | _], _Sid, _ClientMid, _Time, _Info, _extra) ->  %%系统消息
    skip;
ack(From, Sid, ClientMid, Time, Info, Extra) ->
    AckJid = cus_util:make_jid(<<"server_ack">>),
    FromJid = cus_util:make_jid(?l2b(From)),
    ExtraStr = case Extra of
                   [] ->
                       "";
                   _ ->
                       rfc4627:encode({obj, Extra})
               end,
    MsgAck = #messageack{
        mid = ClientMid,
        conversationinfo = pack_proto_conversation_info(Info),
        sid = Sid,
        msgtime = Time,
        extra = ExtraStr},
    ejabberd_router:route(AckJid, FromJid, MsgAck).


get_router_users([$s, $y, $s | _], Info, Message) ->   %%系统消息
    case Message#msg.members of
        "" ->
            Info#cus_conversation.members;
        Members ->
            string:tokens(Members, ",")
    end;
get_router_users(Uid, Info, Message) ->
    List = case Message#msg.members of
               "" ->
                   Info#cus_conversation.members;
               Members ->
                   string:tokens(Members, ",")
           end,
    lists:delete(Uid, List).


get_conversation_infos([], []) ->
    undefined;
get_conversation_infos([], Acc) ->
    Acc;
get_conversation_infos([Cid | T], Acc) ->
    case cus_conversation:conversation_info(Cid) of
        undefined ->
            get_conversation_infos(T, Acc);
        Info ->
            get_conversation_infos(T, [pack_proto_conversation_info(Info) | Acc])
    end.


pack_proto_conversation_info(Info) ->
    #conversationinfo{
        cid = Info#cus_conversation.cid,
        name = Info#cus_conversation.name,
        members = string:join(Info#cus_conversation.members, ","),
        status = Info#cus_conversation.status,
        updatetime = Info#cus_conversation.updateTime}.


push_user(UserInfo) ->
    #cus_push_user{uid = UserInfo#cus_user.uid,
                   muteNotofication = UserInfo#cus_user.muteNotofication,
                   pushContent = UserInfo#cus_user.pushContent,
                   platform = UserInfo#cus_user.platform,
                   pushKey = UserInfo#cus_user.pushKey,
                   muteNotofications = UserInfo#cus_user.muteNotofications}.

